// ----------------------------------------------------------------------------
// container_unit_test.cpp
// ----------------------------------------------------------------------------
#include <fw/base/core/macros.h>
#if defined(FW_ENABLE_UNIT_TEST)
#include <fw/base/core/debugconsole.h>
#include <gtest/gtest.h>
#include <fw/base/container/handle_allocator.h>
#include <fw/base/container/sort_stack.h>
#include <fw/base/container/sort_queue.h>

using namespace fw;

namespace
{
	template <typename T> void HandleAllocatorTest(T& ha, uint16_t maxResourceSize)
	{
		auto& tra = ha;
		
		ASSERT_EQ(tra.GetMaxHandles(), maxResourceSize);
		ASSERT_EQ(tra.GetNumHandles(), 0);
		
		uint16_t rcA = tra.Alloc(); FW_UNUSED(rcA); //FW_PRINTF("rcA = %d\n", rcA);
		uint16_t rcB = tra.Alloc(); FW_UNUSED(rcB); //FW_PRINTF("rcB = %d\n", rcB);
		ASSERT_EQ(tra.GetNumHandles(), 2);
		for(uint16_t rest_i=tra.GetNumHandles(); rest_i<maxResourceSize; ++rest_i)
		{
			tra.Alloc();
		}
		ASSERT_EQ(tra.GetNumHandles(), maxResourceSize);
		
		uint16_t rcX = tra.Alloc(); FW_UNUSED(rcX);
		ASSERT_EQ(rcX, FW_INVALID_HANDLE);
		ASSERT_EQ(tra.GetNumHandles(), maxResourceSize);
		
		tra.Free(rcB);
		tra.Free(rcB); // 二重開放チェック.
		ASSERT_EQ(tra.GetNumHandles(), (maxResourceSize-1));
		
		uint16_t rcE = tra.Alloc(); FW_UNUSED(rcE); //FW_PRINTF("rcE = %d\n", rcE);
		ASSERT_EQ(tra.GetNumHandles(), maxResourceSize);
	}
	
} // unnamed namespace

TEST(container, HandleAllocator)
{
	static const int kMaxResourceSize = 4;
	{
		HandleAllocatorT<kMaxResourceSize> AutoResourceAllocator;
		HandleAllocatorTest<HandleAllocatorT<kMaxResourceSize>>(AutoResourceAllocator, kMaxResourceSize);
	}
	{
		uint8_t* memoryBlock = reinterpret_cast<uint8_t*>(malloc(sizeof(uint16_t)*kMaxResourceSize*2));
		FW_ASSERT(memoryBlock);
		
		HandleAllocator MemoryBlockResourceAllocator(kMaxResourceSize, memoryBlock);
		HandleAllocatorTest<HandleAllocator>(MemoryBlockResourceAllocator, kMaxResourceSize);
		
		free(memoryBlock);
	}
}

TEST(container, SortStack)
{
	typedef SortStack<int> IntegerSortStack;
	IntegerSortStack iss;
	
	ASSERT_EQ(iss.Size(), 0);
	
	iss.Push(6);
	iss.Push(3);
	iss.Push(8);
	iss.Push(12);
	iss.Push(1);

	ASSERT_EQ(iss.Best(), 1);
	
	iss.Pop();
	ASSERT_EQ(iss.Best(), 3);
	ASSERT_EQ(iss.Size(), 4);
}

TEST(container, SortQueue)
{
	typedef SortQueue<int> IntegerSortQueue;
	IntegerSortQueue isq;
	
	ASSERT_EQ(isq.Size(), 0);
	
	isq.Enqueue(-1);
	isq.Enqueue(3);
	isq.Enqueue(8);
	isq.Enqueue(12);
	isq.Enqueue(1);

	ASSERT_EQ(isq.Best(), -1);
	
	isq.Dequeue();
	ASSERT_EQ(isq.Best(), 1);
	ASSERT_EQ(isq.Size(), 4);
}

#endif // FW_ENABLE_UNIT_TEST

void CONTAINER_UNIT_TEST()
{
}
